1. Field of the Invention
Example embodiments of the present invention relate to faster deterministic simulation of arbitrary, unmodified software or code.
2. Description of the Conventional Art
Cost and time expenditure are increasing problems in software development. Often software development projects end up over budget, behind schedule and/or with systems that operate poorly. Using conventional software simulators, software or computer program code may be developed before real hardware systems become available. So long as hardware specifications are available, a virtual hardware model may be created, allowing software development to begin earlier than otherwise would be possible. This may reduce the time-to-market of the software.
Conventional software simulators may be used in simulating software such as operating systems, programming languages, compilers, computer architecture, etc. Conventional simulators may allow greater visibility into systems on which the software is running. For example, when simulating software using a conventional simulator, execution may be stopped and the state of the entire system (e.g., including hardware devices) may be non-intrusively inspected at any time. When simulating operating systems, for example, simulators may allow for more effective resource sharing, while maintaining a higher degree of security. Additionally, conventional simulators may allow hardware failures to be simulated more easily, which may enable hardware failure testing that would be more difficult and/or impossible on real hardware.
One example, conventional technique for simulating software may use an interpreter. An interpreter tracks the state of the simulated processor, memories and/or devices, decodes instructions of the software, and runs routines performing actions of the simulated instructions on the state of the simulated machine. An interpreter, however, may run software slower than a real hardware system with performance similar to that of the host.
Another conventional simulator may use just-in-time compilation. Just-in-time compilation recompiles software into code that may be run directly on a host processor. However, this may also result in slower execution of the software.
To properly simulate software, conventional simulators need to track simulated time. Simulated time may or may not be related to real time, but may be based on a metric of the execution of a simulated system, for example, the number of executed instructions. Simulated time may not be uniform throughout the simulated system, for example, each simulated processor may keep its own time in a multi-processor simulated system.
Simulators need to track simulated time because simulated software may expect certain actions to take time. For example, when an action requiring time is performed, an event specifying that something should happen at a specified point in the future may be posted. For example, when a disk transaction finishes, an interrupt should be raised to the simulated processor. The point in the execution of simulated software at which an event is handled may affect the execution. In order to be deterministic, a simulator must always handle the same event at the same point in the execution. To do so, simulated time must be completely virtualized and may not have any connection to real-time.
Conventional deterministic simulators based on interpreters or just-in-time compilation may count the number of executed instructions and use the result as the time metric. The time at which an event is to be handled may be converted to a number of executed instructions. When that number of instructions has been executed, the interpreter or just-in-time compiled code may stop and handle the event.
Another example manner in which a unique point in the execution of the simulated software may be identified may use a combination of the number of executed branch instructions and a current program counter. When the simulated processor is compatible with the host processor, the software may be simulated by running the software directly on the host processor. This may yield simulation speeds closer to those associated with running the simulated software on real hardware. However, achieving deterministic simulation in this way may be more difficult because identifying the current point in the execution and stopping the execution at the point where an event should be handled may be more difficult and/or impossible.
Simulated software may be deterministically simulated by being run directly on the host processor using the host's hardware performance counters to track the current point in the execution, and using interrupts associated with the performance counters to stop the execution before an event should be handled. Using these techniques target software may be simulated deterministically at speeds closer to speeds achieved when running the software on real hardware. However, these conventional techniques may not completely execute any arbitrary, unmodified program code or software deterministically because the simulated arbitrary, unmodified software and/or program code may overtake the host processor, interfere with host software and/or crash the host when given sufficient privileges. To reduce the likelihood of these occurrences, the simulated software may be run with more limited privileges. However, host processor architectures may not run some parts of the simulated software, (e.g., the kernel of an operating system) with limited privileges. As a result, these portions of the simulated software must be run in an interpreter or be just-in-time compiled. Because these portions of software may constitute a large part of some workloads, this may result in performance degradation.
Alternatively, to reduce the likelihood of the above described occurrences, trusted, non-interfering software (e.g., only software that does not interfere with the host software) may be run on the host processor. However, most workloads must be modified to simulate in this way, and this modification may be difficult and/or impossible. Regardless, all portions of any arbitrary, unmodified software and/or program code may not be run directly on the host processor.
In addition, the architecture of the host processor may be limited, which may limit the virtualization of the processor. That is, for example, it may be impossible to fully virtualize the processor because the simulated software may identify the model of the host processor on which it is running instead of the model of the simulated processor. As a result, the simulated software may read processor registers containing host states, leaking information from the host processor to the simulated processor. This may result in less than complete virtualization of the target and non-determinism if the host state accessed by the simulated processor changes between executions.